﻿namespace ReplayDataFile
{
    using System;
    using System.Collections.Generic;
    using System.Diagnostics;
    using System.IO;
    using System.Runtime.CompilerServices;
    using System.Runtime.InteropServices;

    public class BlockFileReader : BlockFile
    {
        private CachedRecordInfo caches;
        private RecordUnZipper unzipRecord;

        public BlockFileReader(string fileName) : base(fileName)
        {
            this.unzipRecord = new RecordUnZipper();
            this.IsUnzipRecord = true;
            this.caches = new CachedRecordInfo(this);
        }

        public override bool Close()
        {
            return base.Close();
        }

        private void ConvertToFullRecord(List<DataRecord> recList)
        {
            if (base.recordConvertDict.Count != 0)
            {
                Dictionary<int, DataRecord> dictionary = new Dictionary<int, DataRecord>();
                for (int i = 0; i < recList.Count; i++)
                {
                    DataRecord curRecord = recList[i];
                    int dataType = curRecord.DataType;
                    switch (curRecord.RecType)
                    {
                        case DataRecordType.FullDataRecord:
                            dictionary[dataType] = curRecord;
                            break;

                        case DataRecordType.ChangeDataRecord:
                        {
                            RecordConvertProc proc = null;
                            if (base.recordConvertDict.ContainsKey(dataType))
                            {
                                proc = base.recordConvertDict[dataType];
                            }
                            if ((proc != null) && dictionary.ContainsKey(dataType))
                            {
                                DataRecord preRecord = dictionary[dataType];
                                DataRecord record3 = proc(preRecord, curRecord);
                                Debug.Assert(record3 != null);
                                recList[i] = record3;
                            }
                            break;
                        }
                    }
                }
            }
        }

        private List<int> GetDataBlockList(DataTypeDirEntry dirEntry, RecordIndex beginIndex, RecordIndex endIndex)
        {
            List<int> allocBlockList = base.BlockAllocTable.GetAllocBlockList(dirEntry.FirstDataBlock);
            if (beginIndex == null)
            {
                return allocBlockList;
            }
            List<int> list2 = new List<int>();
            bool flag = false;
            foreach (int num in allocBlockList)
            {
                if (num == beginIndex.Block)
                {
                    flag = true;
                }
                if (flag)
                {
                    list2.Add(num);
                }
                if ((endIndex != null) && (num == endIndex.Block))
                {
                    return list2;
                }
            }
            return list2;
        }

        private ICollection<DataTypeDirEntry> GetDataTypeDirSortedByIndexBlock(ICollection<DataTypeDirEntry> dirEntries)
        {
            SortedDictionary<int, DataTypeDirEntry> dictionary = new SortedDictionary<int, DataTypeDirEntry>();
            foreach (DataTypeDirEntry entry in dirEntries)
            {
                dictionary.Add(entry.FirstIndexBlock, entry);
            }
            return dictionary.Values;
        }

        private ICollection<DataTypeDirEntry> GetDataTypeEntries(ICollection<int> dataTypeList)
        {
            if ((dataTypeList == null) || (dataTypeList.Count == 0))
            {
                return this.GetDataTypeDirSortedByIndexBlock(base.DataTypeDir.DirEntries);
            }
            Dictionary<int, DataTypeDirEntry> dictionary = new Dictionary<int, DataTypeDirEntry>();
            foreach (int num in dataTypeList)
            {
                List<DataTypeDirEntry> dirEntryList = base.DataTypeDir.GetDirEntryList(num);
                if (dirEntryList != null)
                {
                    foreach (DataTypeDirEntry entry in dirEntryList)
                    {
                        dictionary[entry.DataType] = entry;
                    }
                }
            }
            return this.GetDataTypeDirSortedByIndexBlock(dictionary.Values);
        }

        private ICollection<int> GetDataTypeFromName(ICollection<string> dataTypeNameList)
        {
            List<int> list = new List<int>();
            foreach (string str in dataTypeNameList)
            {
                int dataTypeId = base.GetDataTypeId(str);
                if (dataTypeId != 0)
                {
                    list.Add(dataTypeId);
                }
            }
            return list;
        }

        private RecordIndex GetFirstBeginRecordIndex(DateTime beginTime, RecordIndex[] indexList)
        {
            if ((indexList != null) && (indexList.Length != 0))
            {
                int length = indexList.Length;
                if (beginTime < indexList[0].Time)
                {
                    return indexList[0];
                }
                for (int i = 0; i < (length - 1); i++)
                {
                    RecordIndex index = indexList[i];
                    RecordIndex index2 = indexList[i + 1];
                    if ((beginTime >= index.Time) && (beginTime < index2.Time))
                    {
                        return index;
                    }
                }
                if (beginTime >= indexList[length - 1].Time)
                {
                    return indexList[length - 1];
                }
            }
            return null;
        }

        private RecordIndex GetFirstEndRecordIndex(DateTime endTime, RecordIndex[] indexList)
        {
            if ((indexList != null) && (indexList.Length != 0))
            {
                int num = indexList.Length - 1;
                for (int i = 0; i < num; i++)
                {
                    RecordIndex index = indexList[i];
                    RecordIndex index2 = indexList[i + 1];
                    if ((endTime > index.Time) && (endTime <= index2.Time))
                    {
                        return index2;
                    }
                }
                if (endTime <= indexList[0].Time)
                {
                    return indexList[0];
                }
                if (endTime > indexList[num].Time)
                {
                    return null;
                }
            }
            return null;
        }

        private void GetFirstRecordIndexRange(long recordNo, RecordIndex[] indexs, out RecordIndex r1, out RecordIndex r2, DataTypeCachedInfo dc)
        {
            r1 = null;
            r2 = null;
            if ((indexs != null) && (indexs.Length != 0))
            {
                for (int i = 0; i < (indexs.Length - 1); i++)
                {
                    r1 = indexs[i];
                    r2 = indexs[i + 1];
                    if ((recordNo >= r1.RecordNo) && (recordNo < r2.RecordNo))
                    {
                        dc.NextIndex = i + 1;
                        return;
                    }
                }
                RecordIndex index = indexs[indexs.Length - 1];
                if (recordNo >= index.RecordNo)
                {
                    r1 = index;
                    r2 = null;
                    dc.NextIndex = indexs.Length;
                }
                else
                {
                    r1 = indexs[0];
                    r2 = (indexs.Length >= 2) ? indexs[1] : null;
                    dc.NextIndex = 1;
                }
            }
        }

        private void GetFirstRecordIndexRange(long minRecNo, DateTime time, RecordIndex[] indexs, out RecordIndex r1, out RecordIndex r2, DataTypeCachedInfo dc)
        {
            r1 = null;
            r2 = null;
            if (indexs != null)
            {
                for (int i = 0; i < (indexs.Length - 1); i++)
                {
                    r1 = indexs[i];
                    r2 = indexs[i + 1];
                    if ((r1.RecordNo >= minRecNo) && ((time >= r1.Time) && (time < r2.Time)))
                    {
                        dc.NextIndex = i + 1;
                        return;
                    }
                }
                RecordIndex index = indexs[indexs.Length - 1];
                if (time >= index.Time)
                {
                    r1 = index;
                    r2 = null;
                    dc.NextIndex = indexs.Length;
                }
                else
                {
                    r1 = indexs[0];
                    r2 = (indexs.Length >= 2) ? indexs[1] : null;
                    dc.NextIndex = 1;
                }
            }
        }

        private RecordIndex GetLastEndRecordIndex(DateTime endTime, RecordIndex[] indexList)
        {
            if ((indexList != null) && (indexList.Length != 0))
            {
                int length = indexList.Length;
                if (endTime > indexList[length - 1].Time)
                {
                    return null;
                }
                for (int i = length - 1; i > 0; i--)
                {
                    RecordIndex index = indexList[i - 1];
                    RecordIndex index2 = indexList[i];
                    if ((endTime > index.Time) && (endTime <= index2.Time))
                    {
                        return index2;
                    }
                }
                if (endTime <= indexList[0].Time)
                {
                    return indexList[0];
                }
            }
            return null;
        }

        public long GetPosition()
        {
            return (this.caches.CurRecordNo - base.Header.FirstRecordNo);
        }

        public override bool Open()
        {
            if (base.isOpened)
            {
                return false;
            }
            lock (this)
            {
                base.isOpened = base.OpenExist(FileAccess.Read, FileShare.ReadWrite);
            }
            return base.isOpened;
        }

        public DataRecord Read(RecordIndex recIndex)
        {
            if (recIndex == null)
            {
                return null;
            }
            DataRecord record = null;
            try
            {
                long offset = base.GetDataBlockInFileOffset(recIndex.Block) + recIndex.OffsetInBlock;
                base.fStream.Seek(offset, SeekOrigin.Begin);
                byte[] buffer = new byte[recIndex.RecordSize];
                base.fStream.Read(buffer, 0, buffer.Length);
                BinaryReader br = new BinaryReader(new MemoryStream(buffer));
                record = new DataRecord();
                if (!record.FromByteBuffer(br, buffer, null))
                {
                    return null;
                }
            }
            catch (Exception exception)
            {
                Trace.WriteLine(" DataRecord Read(RecordIndex recIndex) Error: " + exception.Message);
            }
            return record;
        }

        public List<DataRecord> Read(int dataType)
        {
            List<DataRecord> recList = new List<DataRecord>();
            DataTypeDirEntry dirEntry = base.DataTypeDir.GetDirEntry(dataType);
            if (dirEntry != null)
            {
                List<int> allocBlockList = base.BlockAllocTable.GetAllocBlockList(dirEntry.FirstDataBlock);
                foreach (int num in allocBlockList)
                {
                    int blockUsedSpace = base.BlockAllocTable.GetBlockUsedSpace(num);
                    long dataBlockInFileOffset = base.GetDataBlockInFileOffset(num);
                    base.fStream.Seek(dataBlockInFileOffset, SeekOrigin.Begin);
                    byte[] buffer = new byte[blockUsedSpace];
                    base.fStream.Read(buffer, 0, buffer.Length);
                    BlockInfo blockInfo = base.BlockAllocTable.GetBlockInfo(num);
                    if (!this.ReadDataRecordFromBuffer(recList, buffer, dirEntry.DataType, blockInfo.DataVersion))
                    {
                        return recList;
                    }
                }
            }
            return recList;
        }

        public ICollection<DataRecord> Read(DateTime beginTime, DateTime endTime)
        {
            return this.Read(base.DataTypeDir.DirEntries, beginTime, endTime);
        }

        private List<DataRecord> Read(DataTypeDirEntry dirEntry, RecordIndex beginIndex, RecordIndex endIndex)
        {
            return this.Read(dirEntry, beginIndex, endIndex, false);
        }

        public List<DataRecord> Read(int dataType, RecordIndex beginIndex, RecordIndex endIndex)
        {
            return this.Read(base.DataTypeDir.GetDirEntry(dataType), beginIndex, endIndex);
        }

        public ICollection<DataRecord> Read(string dataTypeName, DateTime beginTime, DateTime endTime)
        {
            int dataTypeId = base.GetDataTypeId(dataTypeName);
            if (dataTypeId == 0)
            {
                return new List<DataRecord>();
            }
            return this.Read(base.DataTypeDir.GetDirEntryList(dataTypeId), beginTime, endTime);
        }

        private ICollection<DataRecord> Read(ICollection<DataTypeDirEntry> entryList, DateTime beginTime, DateTime endTime)
        {
            if (beginTime == endTime)
            {
                endTime = beginTime.AddTicks(1L);
            }
            if ((entryList == null) || (entryList.Count == 0))
            {
                return new List<DataRecord>();
            }
            Dictionary<int, RecordIndex[]> dictionary = this.ReadIndex(entryList);
            SortedDictionary<long, DataRecord> dictionary2 = new SortedDictionary<long, DataRecord>();
            foreach (DataTypeDirEntry entry in entryList)
            {
                RecordIndex[] indexList = null;
                if (dictionary.ContainsKey(entry.DataType))
                {
                    indexList = dictionary[entry.DataType];
                }
                List<DataRecord> recList = null;
                if (indexList == null)
                {
                    recList = this.Read(entry.DataType);
                }
                else
                {
                    RecordIndex firstBeginRecordIndex = this.GetFirstBeginRecordIndex(beginTime, indexList);
                    RecordIndex firstEndRecordIndex = this.GetFirstEndRecordIndex(endTime, indexList);
                    if (firstBeginRecordIndex == null)
                    {
                        continue;
                    }
                    if ((firstBeginRecordIndex == firstEndRecordIndex) && (firstBeginRecordIndex == indexList[indexList.Length - 1]))
                    {
                        firstEndRecordIndex = null;
                    }
                    recList = this.Read(entry, firstBeginRecordIndex, firstEndRecordIndex, true);
                }
                this.ConvertToFullRecord(recList);
                this.RemoveHeadAndTailRecord(recList, beginTime, endTime);
                foreach (DataRecord record in recList)
                {
                    if (!dictionary2.ContainsKey(record.RecordNo))
                    {
                        dictionary2.Add(record.RecordNo, record);
                    }
                }
            }
            return dictionary2.Values;
        }

        public ICollection<DataRecord> Read(List<string> dataTypeNameList, DateTime beginTime, DateTime endTime)
        {
            ICollection<int> dataTypeFromName = this.GetDataTypeFromName(dataTypeNameList);
            return this.Read(this.GetDataTypeEntries(dataTypeFromName), beginTime, endTime);
        }

        public ICollection<DataRecord> Read(int dataType, DateTime beginTime, DateTime endTime)
        {
            return this.Read(base.DataTypeDir.GetDirEntryList(dataType), beginTime, endTime);
        }

        public ICollection<DataRecord> Read(List<int> dataTypeList, DateTime beginTime, DateTime endTime)
        {
            return this.Read(this.GetDataTypeEntries(dataTypeList), beginTime, endTime);
        }

        private List<DataRecord> Read(DataTypeDirEntry dirEntry, RecordIndex beginIndex, RecordIndex endIndex, bool isIncludeEndIndexRecord)
        {
            List<DataRecord> recList = new List<DataRecord>();
            if (dirEntry != null)
            {
                if (beginIndex == null)
                {
                    return this.Read(dirEntry.DataType);
                }
                int recordSize = 0;
                if (isIncludeEndIndexRecord && (endIndex != null))
                {
                    recordSize = endIndex.RecordSize;
                }
                List<int> list2 = this.GetDataBlockList(dirEntry, beginIndex, endIndex);
                foreach (int num2 in list2)
                {
                    int offsetInBlock = 0;
                    int blockUsedSpace = 0;
                    if (endIndex == null)
                    {
                        if (num2 == beginIndex.Block)
                        {
                            offsetInBlock = beginIndex.OffsetInBlock;
                            blockUsedSpace = base.BlockAllocTable.GetBlockUsedSpace(num2) - offsetInBlock;
                        }
                        else
                        {
                            offsetInBlock = 0;
                            blockUsedSpace = base.BlockAllocTable.GetBlockUsedSpace(num2);
                        }
                    }
                    else if (num2 == beginIndex.Block)
                    {
                        offsetInBlock = beginIndex.OffsetInBlock;
                        if (list2.Count == 1)
                        {
                            blockUsedSpace = (endIndex.OffsetInBlock - offsetInBlock) + recordSize;
                        }
                        else
                        {
                            blockUsedSpace = base.BlockAllocTable.GetBlockUsedSpace(num2) - offsetInBlock;
                        }
                    }
                    else if (num2 == endIndex.Block)
                    {
                        blockUsedSpace = endIndex.OffsetInBlock + recordSize;
                    }
                    else
                    {
                        blockUsedSpace = base.BlockAllocTable.GetBlockUsedSpace(num2);
                    }
                    if (blockUsedSpace > 0)
                    {
                        long offset = base.GetDataBlockInFileOffset(num2) + offsetInBlock;
                        base.fStream.Seek(offset, SeekOrigin.Begin);
                        byte[] buffer = new byte[blockUsedSpace];
                        base.fStream.Read(buffer, 0, buffer.Length);
                        BlockInfo blockInfo = base.BlockAllocTable.GetBlockInfo(num2);
                        if (!this.ReadDataRecordFromBuffer(recList, buffer, dirEntry.DataType, blockInfo.DataVersion))
                        {
                            return recList;
                        }
                    }
                }
            }
            return recList;
        }

        public List<DataRecord> Read(int dataType, RecordIndex[] indexs, int startIndex, int readRecCount)
        {
            List<DataRecord> list = new List<DataRecord>();
            if ((((indexs != null) && (startIndex >= 0)) && (startIndex < indexs.Length)) && (readRecCount > 0))
            {
                DataTypeDirEntry dirEntry = base.DataTypeDir.GetDirEntry(dataType);
                if (dirEntry == null)
                {
                    return list;
                }
                if (startIndex == (indexs.Length - 1))
                {
                    return this.Read(dirEntry, indexs[startIndex], null);
                }
                RecordIndex endIndex = null;
                int num = 0;
                for (int i = startIndex; i < (indexs.Length - 1); i++)
                {
                    RecordIndex index2 = indexs[i];
                    RecordIndex index3 = indexs[i + 1];
                    Debug.Assert(index3.RecordNoInKind >= index2.RecordNoInKind);
                    int num3 = index3.RecordNoInKind - index2.RecordNoInKind;
                    num += num3;
                    if (num >= readRecCount)
                    {
                        endIndex = index3;
                        break;
                    }
                }
                list = this.Read(dirEntry, indexs[startIndex], endIndex);
                if (list.Count > readRecCount)
                {
                    list.RemoveRange(readRecCount, list.Count - readRecCount);
                }
            }
            return list;
        }

        private bool ReadDataRecordFromBuffer(List<DataRecord> recList, byte[] buf, int dataType, short dataVer)
        {
            if ((buf == null) || (buf.Length == 0))
            {
                return false;
            }
            BinaryReader br = new BinaryReader(new MemoryStream(buf));
            DataRecord preRecord = null;
            if (recList.Count > 0)
            {
                preRecord = recList[recList.Count - 1];
            }
            try
            {
                DataRecord record2;
                bool flag2;
                goto Label_00C3;
            Label_0052:
                record2 = new DataRecord();
                if (!record2.FromByteBuffer(br, buf, preRecord))
                {
                    goto Label_00DE;
                }
                record2.DataVersion = dataVer;
                record2.DataType = dataType;
                recList.Add(record2);
                preRecord = record2;
                if (this.IsUnzipRecord)
                {
                    this.unzipRecord.UnZip(record2);
                }
                if (br.BaseStream.Position >= buf.Length)
                {
                    goto Label_00DE;
                }
            Label_00C3:
                flag2 = true;
                goto Label_0052;
            }
            catch (Exception exception)
            {
                Trace.WriteLine(exception.Message);
                return false;
            }
        Label_00DE:
            return true;
        }

        private Dictionary<int, RecordIndex[]> ReadIndex(ICollection<DataTypeDirEntry> entryList)
        {
            Dictionary<int, RecordIndex[]> dictionary = new Dictionary<int, RecordIndex[]>();
            foreach (DataTypeDirEntry entry in this.GetDataTypeDirSortedByIndexBlock(entryList))
            {
                RecordIndex[] indexArray = this.ReadIndex(entry.DataType);
                if (indexArray != null)
                {
                    dictionary.Add(entry.DataType, indexArray);
                }
            }
            return dictionary;
        }

        public RecordIndex[] ReadIndex(int dataType)
        {
            int num6;
            DataTypeDirEntry dirEntry = base.DataTypeDir.GetDirEntry(dataType);
            if (dirEntry == null)
            {
                return null;
            }
            if (!dirEntry.IsWriteIndex)
            {
                return null;
            }
            List<int> allocBlockList = base.BlockAllocTable.GetAllocBlockList(dirEntry.FirstIndexBlock);
            if ((allocBlockList == null) || (allocBlockList.Count == 0))
            {
                return null;
            }
            int indexRecordCount = dirEntry.IndexRecordCount;
            int blockSize = base.Header.BlockSize;
            long num3 = indexRecordCount * RecordIndex.Size;
            int count = (blockSize / RecordIndex.Size) * RecordIndex.Size;
            if (num3 != ((count * (allocBlockList.Count - 1)) + dirEntry.IndexBlockOffset))
            {
                Trace.WriteLine("索引记录数和索引数据块中的数据长度不一致。");
                return null;
            }
            byte[] buffer = new byte[num3];
            int offset = 0;
            for (num6 = 0; num6 < allocBlockList.Count; num6++)
            {
                int blockIndex = allocBlockList[num6];
                long dataBlockInFileOffset = base.GetDataBlockInFileOffset(blockIndex);
                if (num6 == (allocBlockList.Count - 1))
                {
                    count = dirEntry.IndexBlockOffset;
                }
                base.fStream.Seek(dataBlockInFileOffset, SeekOrigin.Begin);
                base.fStream.Read(buffer, offset, count);
                offset += count;
            }
            RecordIndex[] indexArray = new RecordIndex[indexRecordCount];
            BinaryReader br = new BinaryReader(new MemoryStream(buffer));
            for (num6 = 0; num6 < indexArray.Length; num6++)
            {
                indexArray[num6] = new RecordIndex();
                indexArray[num6].FromByteBuffer(br);
                indexArray[num6].FileId = base.Header.FileId;
            }
            return indexArray;
        }

        public List<RecordIndex> ReadIndex(int dataType, DateTime beginTime, DateTime endTime)
        {
            List<RecordIndex> list = new List<RecordIndex>();
            if (base.DataTypeDir.GetDirEntry(dataType) != null)
            {
                int num3;
                RecordIndex[] indexArray = this.ReadIndex(dataType);
                if (indexArray == null)
                {
                    return list;
                }
                int num = 0;
                int length = indexArray.Length;
                for (num3 = 0; num3 < indexArray.Length; num3++)
                {
                    if (indexArray[num3].Time >= beginTime)
                    {
                        num = num3;
                        break;
                    }
                }
                for (num3 = indexArray.Length - 1; num3 >= 0; num3--)
                {
                    if (endTime < indexArray[num3].Time)
                    {
                        length = num3;
                        break;
                    }
                }
                for (num3 = num; num3 < length; num3++)
                {
                    list.Add(indexArray[num3]);
                }
            }
            return list;
        }

        public List<DataRecord> ReadNext(int count)
        {
            return this.caches.ReadCacheRecord(count);
        }

        private void RemoveHeadAndTailRecord(List<DataRecord> recList, DateTime beginTime, DateTime endTime)
        {
            int num2;
            Dictionary<int, DataRecord> dictionary = new Dictionary<int, DataRecord>();
            Dictionary<int, DataRecord> dictionary2 = new Dictionary<int, DataRecord>();
            int count = 0;
            for (num2 = 0; num2 < recList.Count; num2++)
            {
                DataRecord record = recList[num2];
                if (record.Time < beginTime)
                {
                    count++;
                    dictionary[record.DataType] = record;
                }
                else
                {
                    dictionary2[record.DataType] = record;
                    break;
                }
            }
            if (count > 0)
            {
                recList.RemoveRange(0, count);
            }
            SortedDictionary<long, DataRecord> dictionary3 = new SortedDictionary<long, DataRecord>();
            foreach (DataRecord record in dictionary.Values)
            {
                DataRecord record2 = new DataRecord(record) {
                    IsInterpolationRecord = true
                };
                if (dictionary2.ContainsKey(record.DataType))
                {
                    DataRecord record3 = dictionary2[record.DataType];
                    if (record3.RecType == DataRecordType.StartupRecord)
                    {
                        record2.RecType = DataRecordType.ExitRecord;
                    }
                }
                if (record2.RecType == DataRecordType.FullDataRecord)
                {
                    record2.Time = beginTime;
                }
                dictionary3.Add(record2.RecordNo, record2);
            }
            recList.InsertRange(0, dictionary3.Values);
            int num3 = 0;
            for (num2 = recList.Count - 1; num2 >= 0; num2--)
            {
                if (recList[num2].Time < endTime)
                {
                    break;
                }
                num3++;
            }
            if (num3 > 0)
            {
                recList.RemoveRange(recList.Count - num3, num3);
            }
        }

        public long SetPosition(DateTime time)
        {
            return this.SetPosition(0L, time, null);
        }

        public long SetPosition(long recordNo)
        {
            return this.SetPosition(recordNo, null);
        }

        public long SetPosition(DateTime time, List<int> dataTypeList)
        {
            return this.SetPosition(0L, time, dataTypeList);
        }

        public long SetPosition(long recordNo, List<int> dataTypeList)
        {
            if (recordNo > base.Header.RecordNo)
            {
                return -1L;
            }
            this.caches.Clear();
            foreach (DataTypeDirEntry entry in this.GetDataTypeEntries(dataTypeList))
            {
                RecordIndex[] indexs = this.ReadIndex(entry.DataType);
                if ((indexs != null) && (indexs.Length != 0))
                {
                    if (!this.caches.ChachedDataTypes.ContainsKey(entry.DataType))
                    {
                        this.caches.ChachedDataTypes.Add(entry.DataType, new DataTypeCachedInfo(this));
                    }
                    DataTypeCachedInfo dc = this.caches.ChachedDataTypes[entry.DataType];
                    dc.DataType = entry.DataType;
                    dc.RecIndexs = indexs;
                    RecordIndex index = null;
                    RecordIndex index2 = null;
                    this.GetFirstRecordIndexRange(recordNo, indexs, out index, out index2, dc);
                    List<DataRecord> list = this.Read(entry, index, index2);
                    dc.CachedRecordList = list;
                    this.caches.CurRecordNo = recordNo;
                }
            }
            return recordNo;
        }

        public long SetPosition(long minRecNo, DateTime time, List<int> dataTypeList)
        {
            long recordNo = 0x7fffffffffffffffL;
            this.caches.Clear();
            Dictionary<int, DataRecord> dictionary = new Dictionary<int, DataRecord>();
            Dictionary<int, DataRecord> dictionary2 = new Dictionary<int, DataRecord>();
            foreach (DataTypeDirEntry entry in this.GetDataTypeEntries(dataTypeList))
            {
                RecordIndex[] indexs = this.ReadIndex(entry.DataType);
                if ((indexs != null) && (indexs.Length != 0))
                {
                    if (!this.caches.ChachedDataTypes.ContainsKey(entry.DataType))
                    {
                        this.caches.ChachedDataTypes.Add(entry.DataType, new DataTypeCachedInfo(this));
                    }
                    DataTypeCachedInfo dc = this.caches.ChachedDataTypes[entry.DataType];
                    dc.DataType = entry.DataType;
                    dc.RecIndexs = indexs;
                    RecordIndex index = null;
                    RecordIndex index2 = null;
                    this.GetFirstRecordIndexRange(minRecNo, time, indexs, out index, out index2, dc);
                    List<DataRecord> list = this.Read(entry, index, index2, true);
                    dc.CachedRecordList = list;
                    for (int i = 0; i < list.Count; i++)
                    {
                        DataRecord record = list[i];
                        if (record.Time > time)
                        {
                            dictionary2[entry.DataType] = record;
                            break;
                        }
                        dictionary[entry.DataType] = record;
                    }
                    if (((list.Count > 0) && (index2 != null)) && (list[list.Count - 1].RecordNo == index2.RecordNo))
                    {
                        list.RemoveAt(list.Count - 1);
                    }
                }
            }
            if (dictionary.Count > 0)
            {
                SortedDictionary<long, DataRecord> dictionary3 = new SortedDictionary<long, DataRecord>();
                recordNo = -9223372036854775808L;
                foreach (DataRecord record in dictionary.Values)
                {
                    if (record.RecordNo > recordNo)
                    {
                        recordNo = record.RecordNo;
                    }
                    if (record.RecType == DataRecordType.FullDataRecord)
                    {
                        record.IsInterpolationRecord = true;
                        if (dictionary2.ContainsKey(record.DataType))
                        {
                            DataRecord record2 = dictionary2[record.DataType];
                            if (record2.RecType == DataRecordType.StartupRecord)
                            {
                                record.RecType = DataRecordType.ExitRecord;
                            }
                        }
                        if (record.RecType == DataRecordType.FullDataRecord)
                        {
                            record.Time = time;
                        }
                    }
                    dictionary3[record.RecordNo] = record;
                }
                foreach (DataRecord record in dictionary3.Values)
                {
                    this.caches.AddCacheRecord(record);
                }
                this.caches.CurRecordNo = recordNo;
            }
            else if (dictionary2.Count > 0)
            {
                recordNo = 0x7fffffffffffffffL;
                foreach (DataRecord record in dictionary2.Values)
                {
                    if (record.RecordNo < recordNo)
                    {
                        recordNo = record.RecordNo;
                    }
                }
                this.caches.CurRecordNo = recordNo;
            }
            return ((recordNo == 0x7fffffffffffffffL) ? -1L : recordNo);
        }

        public bool IsUnzipRecord { get; set; }
    }
}

